import { useState, ReactNode, useCallback, useEffect } from 'react';
import classNames from 'classnames';
import { FormModal } from '../form-modal';
import { Check, ChevronDown, Loader2, Search, X } from 'lucide-react';
import { Checkbox } from '@/components/ui/checkbox';
import '../form.css';
import { useDebounce } from '../_hooks/use-debounce';
import MyInput from '../my-input';

// ==============================================
// 类型定义（优化泛型，明确单选/多选类型）
// ==============================================

/** 单个选项的结构 */
export interface SelectOption<T = string> {
  label: ReactNode; // 选项显示内容
  value: T; // 选项实际值（支持任意类型）
  [key: string]: any; // 允许扩展其他属性
}

/** 辅助类型：根据多选状态推导值类型 */
type SelectValue<T, IsMultiple> = IsMultiple extends true ? T[] | undefined : T | undefined;

/** 
 * MySelect 组件属性接口
 * @template T 选项值的类型（如 string、number、object 等）
 * @template IsMultiple 是否为多选模式（boolean 类型字面量）
 */
export interface SelectProps<T = string, IsMultiple extends boolean = false> {
  name?: string; // 必填 当前组件的名词，如Phone Email等
  options: SelectOption<T>[]; // 选项列表
  multiple?: IsMultiple; // 是否开启多选（与 IsMultiple 泛型绑定）
  value: SelectValue<T, IsMultiple>; // 选中值（根据 IsMultiple 动态推导）
  onChange: (value: SelectValue<T, IsMultiple>) => void; // 回调参数类型与 value 一致
  placeholder?: string; // 未选择时的占位符
  disabled?: boolean; // 禁用整个组件
  className?: string; // 自定义容器类名
  triggerRender?: (value: SelectValue<T, IsMultiple>) => ReactNode; // 自定义触发器
  contentClassName?: string; // 自定义内容类名
  showSearch?: boolean; // 是否展示搜索
  prefix?: ReactNode; // triggerRender下不生效 自定义前缀
  suffix?: ReactNode; // triggerRender下不生效 自定义后缀
  loading?: boolean; // 是否加载中
}

export function MySelect<T, IsMultiple extends boolean = false>({
  name = '',
  options,
  multiple = false as IsMultiple, // 绑定到 IsMultiple 泛型
  value,
  onChange,
  placeholder,
  disabled = false,
  className,
  triggerRender,
  contentClassName,
  showSearch = false,
  prefix,
  suffix,
  loading = false
}: SelectProps<T, IsMultiple>) {
  // modal弹窗的状态
  const [open, setOpen] = useState(false)

  // 处理延时生效的选中状态,点击确定后才会生效(多选)
  const [tempValue, setTempValue] = useState<SelectValue<T, IsMultiple>>(value)

  // 搜索框的值
  const [searchValue, setSearchValue] = useState('')
  // 展示的options：搜索效果
  const [showOptions, setShowOptions] = useState(options)
  // 搜索的防抖
  const debouncedSearchValue = useDebounce(searchValue, 500)
  useEffect(() => {
    setShowOptions(options.filter((option) => option.label && option.label.toString().toLowerCase().includes(debouncedSearchValue.toLowerCase())))
  }, [debouncedSearchValue, options])

  // 通用的处理方法等 -------------------------------------------------------------------------------
  // 外部点击清除所有
  const handleClearAll = () => {
    onChange(undefined)
    setTempValue(undefined)
    setOpen(false)
  }

  // 选择方法处理 -------------------------------------------------------------------------------
  // 单选
  const handleSingleSelect = useCallback(
    (option: SelectOption<T>) => {
      // 单选时，value 为 T | undefined， newValue 类型匹配
      const newValue = value === option.value ? undefined : option.value;
      onChange(newValue as SelectValue<T, IsMultiple>);
      setOpen(false)
    },
    [value, onChange]
  );

  // 多选
  const handleMultiSelect = useCallback(
    (option: SelectOption<T>) => {
      // 多选时，value 为 T[] | undefined
      const currentValues = Array.isArray(tempValue) ? [...tempValue] : [];
      const isMultiSelected = currentValues.includes(option.value);

      let newValue: T[] | undefined;
      if (isMultiSelected) {
        newValue = currentValues.filter((v) => v !== option.value);
        if (newValue.length === 0) newValue = undefined;
      } else {
        newValue = [...currentValues, option.value];
      }
      setTempValue(newValue as SelectValue<T, IsMultiple>);
    },
    [tempValue, onChange]
  );

  // 判断option是否是选中状态 -------------------------------------------------------------------------------
  // 单选(通过value判断)
  const isSingleSelected = (option: SelectOption<T>) => {
    if (multiple) {
      return Array.isArray(value) && value.includes(option.value)
    }
    return value === option.value
  }

  // 多选(通过tempValue判断)
  const isMultiSelected = (option: SelectOption<T>) => {
    if (multiple) {
      return Array.isArray(tempValue) && tempValue.includes(option.value)
    }
    return tempValue === option.value
  }

  // 判断value是否是有效值
  // 单选
  const isSingleValid = (value: SelectValue<T, IsMultiple>) => {
    return value !== undefined && value !== null
  }
  // 多选
  const isMultiValid = (value: SelectValue<T, IsMultiple>) => {
    if (multiple) {
      return Array.isArray(value) && value.length > 0
    }
    return value !== undefined && value !== null
  }

  // option渲染 -------------------------------------------------------------------------------
  // 单选
  const singleOption = (option: SelectOption<T>) => <div className='flex items-center justify-between gap-2 cursor-pointer hover:bg-black/10 transition-all duration-100 py-2 px-2 rounded-sm'>
    {option.label}
    {<Check className={classNames('w-4 h-4', {
      'hidden': !isSingleSelected(option)
    })} />}
  </div>

  // 多选
  const multiOption = (option: SelectOption<T>) => <div className='flex items-center gap-2 cursor-pointer hover:bg-black/10 transition-all duration-100 py-2 px-2 rounded-sm'>
    <Checkbox checked={isMultiSelected(option)} />
    {option.label}
  </div>

  // defaultTrigger渲染 -------------------------------------------------------------------------------
  // 单选
  const singleDefaultTrigger = (
    <div 
      onClick={()=>{setOpen(true)}}
      className={classNames('select-layout group flex items-center gap-2', {
        'select-layout--focus': open,
        'select-layout--disabled': disabled || loading,
        'select-layout--placeholder': !isSingleValid(value),
        'select-layout--active': isSingleValid(value)
      }, className)}>
      {/* 前缀 */}
      {prefix}
      {/* 文本 */}
      <div className={classNames('select-text')}>{isSingleValid(value) ? options.find((option) => option.value === value)?.label : placeholder}</div>
      {/* 操作指示器 */}
      <div className='select-indicator'>
        {!loading && <>
          <div className='select-indicator-container'>
            <ChevronDown className={classNames('select-indicator-arrow', {
              'rotate-180': open
            })} />
          </div>
          <div className='select-indicator-container'>
            <X className={classNames('select-indicator-close opacity-0 group-hover:opacity-100 transition-all duration-100', {
              'hidden': !isSingleValid(value)
            })}
              onClick={(e) => {
                e?.stopPropagation();
                handleClearAll();
              }}
            />
          </div>
        </>}
        {loading && <div className='select-indicator-container'>
          <Loader2 className='select-indicator-loading' />
        </div>}
      </div>
      {/* 后缀 */}
      {suffix}
    </div>  
  )

  // 多选
  const multiDefaultTrigger = (
    <div 
      onClick={()=>{setOpen(true)}}
      className={classNames('select-layout group flex items-center gap-2', {
        'select-layout--focus': open,
        'select-layout--disabled': disabled || loading,
        'select-layout--placeholder': !isMultiValid(value),
        'select-layout--active': isMultiValid(value)
      }, className)}>
      {/* 前缀 */}
      {prefix}
      {/* 文本 */}
      <div className={classNames('select-text')}>{(isMultiValid(value)) ? options.filter((option) => Array.isArray(value) && value.includes(option.value)).map((option) => option.label).join(', ') : placeholder}</div>
      {/* 操作指示器 */}
      <div className='select-indicator'>
        {!loading && <>
          <div className='select-indicator-container'>
            <ChevronDown className={classNames('select-indicator-arrow', {
              'rotate-180': open
            })} />
          </div>
          <div className='select-indicator-container'>
            <X className={classNames('select-indicator-close opacity-0 group-hover:opacity-100 transition-all duration-100', {
              'hidden': !isMultiValid(value)
            })}
              onClick={(e) => {
                e?.stopPropagation();
                handleClearAll();
              }}
            />
          </div>
        </>}
        {loading && <div className='select-indicator-container'>
          <Loader2 className='select-indicator-loading' />
        </div>}
      </div>
      {/* 后缀 */}
      {suffix}
    </div>
  )

  return (
    <FormModal
      open={open}
      onOpenChange={setOpen}
      header={name}
      trigger={ (triggerRender && triggerRender(value)) || (multiple ? multiDefaultTrigger : singleDefaultTrigger)} 
      className={contentClassName}
      showMaxSize={showSearch}
      slot={
        showSearch ? <MyInput value={searchValue} onChange={(e) => setSearchValue(e || '')} placeholder={`Search ${name}`} prefix={<Search className='w-4 h-4' />} /> : null
      }
      content={
        <ul className={classNames('flex flex-col')}>
          {showOptions.length > 0 ? showOptions.map((option, index) => (
            <li 
              onClick={
                () => (multiple ? handleMultiSelect(option) : handleSingleSelect(option))
              } key={index}>
                {multiple ? multiOption(option) : singleOption(option)}
            </li>
          )) : <div className='flex items-center justify-center h-full'>No options</div>}
        </ul>
      }
      footer={
        multiple? <div className='flex gap-2'>
          <button className='flex-1 border border-black rounded-sm px-2 py-1 bg-transparent text-black' onClick={()=>{
            setTempValue(undefined)
          }}>Clear All</button>
          <button className='flex-1 border border-black rounded-sm px-2 py-1 bg-black text-white' onClick={()=>{
            onChange(tempValue as SelectValue<T, IsMultiple>)
            setOpen(false)
          }}>
            {/* Selected { Array.isArray(tempValue) ? tempValue.length : 0 } items */}
            Confirm
          </button>
        </div> : null
      }>
    </FormModal>
  );
}